package com.gonsin.i18n.lib.view;

import android.os.Handler;
import android.util.Log;

import androidx.annotation.MainThread;

import com.gonsin.i18n.lib.common.TextObserver;
import com.gonsin.i18n.lib.common.TextResult;
import com.gonsin.i18n.lib.config.TConfig;
import com.gonsin.i18n.lib.utils.AESUtils;
import com.gonsin.i18n.lib.utils.ThreadUtils;
import com.google.gson.Gson;

//import org.apache.http.HttpResponse;
//import org.apache.http.client.ClientProtocolException;
//import org.apache.http.client.ResponseHandler;
//import org.apache.http.client.methods.HttpPost;
//import org.apache.http.impl.client.CloseableHttpClient;
//import org.apache.http.impl.client.DefaultHttpClient;
//import org.apache.http.impl.client.HttpClientBuilder;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class TextManager {

    private String lang;        // 当前语言

    private Map<String, String> textMap = new HashMap<>();        // 语言表

    private Map<String, String> textCommonMap = new HashMap<>();        // 语言表

    private TConfig config;

    private AtomicBoolean langUpdated = new AtomicBoolean(false);

    private Set<TextObserver> observers = new HashSet<>();

    // 定时器拉取新的字符串是否已开启
    private boolean timerStarted = false;

    // 定时器定时检查新的字符串是否已开启
    private boolean checkerStarted = false;

    private boolean autoUploadNewText = true;

    private Handler uiHandler;      // 主线程调用

    private List<String> langs;

    private AtomicBoolean loadFinished = new AtomicBoolean(false);

    private Map<String, Set<String>> newTexts = new HashMap<>();

    private Timer loadTimer;

    private Timer checkTimer;

    public void setTextList(Map<String, String> map) {
        this.textMap.clear();
        this.textMap.putAll(map);
    }

    public Map<String, String> getTextList() {
        return this.textMap;
    }

    /**
     * 获取真正的字符串内容
     */
    public String getText(String originText, Object ... args) {
        originText = originText.replace("\n", "\\n");
        String after = textMap.get(originText);
        if(after == null){
            synchronized (this) {
                Set<String> texts = newTexts.get(lang);
                if(texts == null){
                    texts = new ConcurrentSkipListSet<>();
                    newTexts.put(lang, texts);
                }
                texts.add(originText);

                if (autoUploadNewText) {
                    Map<String, Set<String>> newText = new HashMap<>();
                    Set<String> text = new ConcurrentSkipListSet<>();
                    text.add(originText);
                    newText.put(lang, text);
                    new Thread(() -> {
                        uploadNewTexts(newText);
                    }).start();
                }
            }
            textMap.put(originText, originText);
        }
        return (after == null ? String.format(originText, args) :
                String.format(after, args))
                .replace("\\n", "\n");
    }


    

    /**
     * 获取真正的字符串内容
     */
    public String getTextWithCommon(String originText, String common) {
        originText = originText.replace("\n", "\\n");
        String after = textMap.get(originText);
        if(after == null){
            synchronized (this) {
                Set<String> texts = newTexts.get(lang);
                if(texts == null){
                    texts = new ConcurrentSkipListSet<>();
                    newTexts.put(lang, texts);
                }
                texts.add(originText);

                if (autoUploadNewText) {
                    Map<String, Set<String>> newText = new HashMap<>();
                    Set<String> text = new ConcurrentSkipListSet<>();
                    text.add(originText);
                    newText.put(lang, text);
                    new Thread(() -> {
                        uploadNewTexts(newText);
                    }).start();
                }
            }
            textMap.put(originText, originText);
            if(common != null && !"".equals(common)){
                textCommonMap.put(originText, common);
            }
        }
        return (after == null ? String.format(originText) :
                String.format(after))
                .replace("\\n", "\n");
    }




    /**
     * 查询云端支持的语言
     */
    public List<String> getLangs(){
        if(langs == null){
            try {
                langs = getLangsAync().get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return langs;
    }


    /**
     * 异步查询语言列表
     * @return
     */
    public Future<List<String>> getLangsAync(){

        return ThreadUtils.submit(new Callable<List<String>>() {
            @Override
            public List<String> call() throws Exception {


                String url = config.isUseSSL() ? "https://" : "http://" + config.getIp() + ":" + config.getPort();

                // 将请求进行加密处理
                url = url + "/api/i18n/" + config.getProject();

                try {
                    Request request = new Request.Builder()
                            .url(url)
//                            .method("post", RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), (String)null))
                            .post(RequestBody.create(MediaType.parse("application/json; charset=utf-8"), ""))
                            .build();
                    OkHttpClient client = new OkHttpClient.Builder().build();
                    Response response = client.newCall(request).execute();
                    String temp = response.body().string();
                    temp = AESUtils.decryptECB(temp, config.getKey(), config.getEncoder());
                    Map<String, Object> map = new Gson().fromJson(temp, Map.class);
                    return (List<String>) map.get("data");
                } catch (Exception ex){
                    ex.printStackTrace();
                }

//                try(CloseableHttpClient client = new DefaultHttpClient()) {
//                    String url = config.isUseSSL() ? "https://" : "http://" + config.getIp() + ":" + config.getPort();
//
//                    // 将请求进行加密处理
//                    url = url + "/api/i18n/" + config.getProject();
//                    HttpPost post = new HttpPost(url);
//                    List<String> result = client.execute(post, new ResponseHandler<List<String>>() {
//                        @Override
//                        public List<String> handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
//                            try {
//                                ByteArrayOutputStream output = new ByteArrayOutputStream();
//                                response.getEntity().writeTo(output);
//                                String result = output.toString(config.getEncoder());
//
//                                // 对返回的内容进行解密
//                                result = AESUtils.decryptECB(result, config.getKey(), config.getEncoder());
//                                Map<String, Object> map = new Gson().fromJson(result, Map.class);
//                                return (List<String>) map.get("data");
//                            } catch (Exception ex) {
//                                ex.printStackTrace();
//                                return new ArrayList<>();
//                            }
//                        }
//                    });
//                    return result;
//                } catch (Throwable e) {
//                    e.printStackTrace();
//                } finally {
//                }
                return new ArrayList<>();
            }
        });
    }



    /**
     * 加载字符串
     */
    public TextResult loadSync() {
        if("".equals(lang) || null == lang){
            return TextResult.LANG_NOT_SET;
        }

        try {
            this.loadFinished.set(false);

            String url = config.isUseSSL() ? "https://" : "http://" + config.getIp() + ":" + config.getPort();
            url = url + "/api/i18n/" + config.getProject() + "/" + lang;
            Request request = new Request.Builder()
                    .url(url)
                    .post(RequestBody.create(MediaType.parse("application/json; charset=utf-8"), ""))
                    .build();
            OkHttpClient client = new OkHttpClient.Builder().build();
            Response response = client.newCall(request).execute();
            String temp = response.body().string();

            // 对返回的内容进行解密
            temp = AESUtils.decryptECB(temp, config.getKey(), config.getEncoder());
            TextResult result = new Gson().fromJson(temp, TextResult.class);

            if(config.isDebug()){
                Log.e("T", "开始拉取语言");
            }
            if(result.getState() == 200){
                Map<String, String> newMap = result.getData();
                // 比较2个map是否相同
                if(isSame(textMap, newMap)){
                    return result;
                }
                textMap.clear();
                textMap.putAll(result.getData());
                // 刷新
                notifyTextChanged();
            }

            return result;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            this.langUpdated.set(false);
            this.loadFinished.set(true);
        }


//        try(CloseableHttpClient client = new DefaultHttpClient()) {
//
//            // 将请求进行加密处理
//            url = url + "/api/i18n/" + config.getProject() + "/" + lang;
//            HttpPost post = new HttpPost(url);
//
//            TextResult result = client.execute(post, new ResponseHandler<TextResult>() {
//                @Override
//                public TextResult handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
//                    try {
//                        ByteArrayOutputStream output = new ByteArrayOutputStream();
//                        response.getEntity().writeTo(output);
//                        String result = output.toString(config.getEncoder());
//
//                        // 对返回的内容进行解密
//                        result = AESUtils.decryptECB(result, config.getKey(), config.getEncoder());
//                        return new Gson().fromJson(result, TextResult.class);
//                    } catch (Exception ex) {
//                        ex.printStackTrace();
//                        return TextResult.FAILED;
//                    }
//                }
//            });
//
//            if(config.isDebug()){
//                Log.e("T", "开始拉取语言");
//            }
//            if(result.getState() == 200){
//                textMap.clear();
//                textMap.putAll(result.getData());
//                // 刷新
//                notifyTextChanged();
//            }
//
//
//            return result;
//        } catch (Throwable e) {
//            e.printStackTrace();
//            if(config.isDebug()){
//                Log.e("T", e.getMessage());
//            }
//        } finally {
//            this.langUpdated.set(false);
//            this.loadFinished.set(true);
//        }
        return TextResult.FAILED;
    }

    /**
     *
     * @param oldMap
     * @param newMap
     * @return
     */
    private boolean isSame(Map<String, String> oldMap, Map<String, String> newMap) {
        if(oldMap == null && newMap == null){
            return true;
        }
        if(oldMap != null && newMap == null){
            return false;
        }
        if(oldMap == null && newMap != null){
            return false;
        }
        Set<String> oldKeys = oldMap.keySet();
        Set<String> newKeys = newMap.keySet();
        if(!isSame(oldKeys, newKeys)){
            return false;
        }
        if(oldKeys.isEmpty() && newKeys.isEmpty()){
            return true;
        }
        Collection<String> oldValues = oldMap.values();
        Collection<String> newValues = newMap.values();
        if(!isSame(oldValues, newValues)){
            return false;
        }

        for(String key : oldKeys){
            String oldValue = oldMap.get(key);
            String newValue = newMap.get(key);
            if(oldValue == null && newValue == null){
                continue;
            }
            if(oldValue != null && newValue == null){
                return false;
            }
            if(oldValue == null && newValue != null){
                return false;
            }
            if(!oldValue.equals(newValue)){
                return false;
            }
        }

        return true;
    }

    private boolean isSame(Collection<String> oldValues, Collection<String> newValues) {
        if(oldValues == null && newValues == null){
            return true;
        }
        if(oldValues != null && newValues == null){
            return false;
        }
        if(oldValues == null && newValues != null){
            return false;
        }
        if(oldValues.size() != newValues.size()){
            return false;
        }
        if(oldValues.containsAll(newValues) && newValues.containsAll(oldValues)){
            return true;
        }
        return false;
    }

    /**
     * 通知到前端，字符串有改动
     */
    public void notifyTextChanged() {
        if(observers.size() == 0){
            return;
        }
        uiHandler.post(new Runnable() {
            @Override
            public void run() {
                for (TextObserver o : observers){
                    o.applyText();
                }
            }
        });
    }

    /**
     * 配置初始化
     */
    @MainThread
    public void config(TConfig config) {
        this.config = config;
        if(config.isDebug()){
            // 创建定时器，定时更新字符串
            initTimer();

            // 创建定时器，定时将本地新的字符串资源上传到服务器
            initChecker();
        }


        uiHandler = new Handler();
        //getLangsAync();
    }


    private void initTimer(){
        if(timerStarted){
            return;
        }
        timerStarted = true;
        loadTimer = new Timer();
        loadTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                if(lang == null || lang.equals("")){
                    return;
                }
                loadSync();
            }
        }, 60000);
    }


    private void initChecker(){
        if(checkerStarted){
            return;
        }
        checkerStarted = true;
        checkTimer = new Timer();
        checkTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                uploadNewTexts();
            }
        }, 10000);
    }

    /**
     * 定时上传新字符串
     */
    public void uploadNewTexts() {
        uploadNewTexts(newTexts);
    }

    private void uploadNewTexts(Map<String, Set<String>> newTexts) {

        if(newTexts.isEmpty()){
            return;
        }

        if(config.isDebug()){
            Log.e("T", "将字符串上传到服务器上");
        }

        Map<String, Set<String>> tempMap = new HashMap<>(newTexts);

        Set<String> langs = tempMap.keySet();
        for(String l : langs){
            Set<String> words = tempMap.get(l);
            if(words == null || words.isEmpty()){
                continue;
            }
            Iterator<String> iterator = words.iterator();
            while(iterator.hasNext()){

                try {
                    String w = iterator.next();
                    if(w == null){
                        iterator.remove();
                        continue;
                    }
                    String url = config.isUseSSL() ? "https://" : "http://" + config.getIp() + ":" + config.getPort();
                    url = url + "/api/i18n/" + config.getProject() + "/" + l;
                    String encodeWord = AESUtils.encryptECB(w, config.getKey(), config.getEncoder());
                    FormBody.Builder fb = new FormBody.Builder();
                    fb.add("keyword", encodeWord);
                    String common = textCommonMap.get(w);
                    if(common != null){
                        fb.add("common", common);
                    }
                    Request request = new Request.Builder()
                            .url(url)
                            .put(fb.build())
                            .build();
                    OkHttpClient client = new OkHttpClient.Builder().build();
                    Response response = client.newCall(request).execute();
                    String temp = response.body().string();

                    // 对返回的内容进行解密
                    temp = AESUtils.decryptECB(temp, config.getKey(), config.getEncoder());
                    TextResult result = new Gson().fromJson(temp, TextResult.class);
                    if(result.getState() == 200){
                        iterator.remove();
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                } finally {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
            if(words.isEmpty()){
                tempMap.remove(l);
            }
        }

        synchronized (this){
            newTexts = tempMap;
        }

    }

    public void setAutoUploadNewText(boolean autoUploadNewText) {
        this.autoUploadNewText = autoUploadNewText;
    }

    public String getLang() {
        return lang;
    }

    /**
     * 修改语言
     */
    public void setLang(String lang) {
        this.lang = lang;
        this.langUpdated.set(true);
    }


    private static TextManager instance;
    public static TextManager getInstance() {
        if(instance == null){
            instance = new TextManager();
        }
        return instance;
    }

    /**
     * 添加字符串观察者（用于字符串变化时更新前端）
     */
    public void addObserver(TextObserver observer) {
        observers.add(observer);
    }

    /**
     * 添加字符串观察者（用于字符串变化时更新前端）
     */
    public void removeObserver(TextObserver observer) {
        observers.remove(observer);
    }

    /**
     * 是否加载完成
     */
    public boolean isLoadFinished() {
        return loadFinished.get();
    }
}
